home *** CD-ROM | disk | FTP | other *** search
- /* AT: (c) Kees Lemmens, Netherlands; June 1993.
-
- This tool can start a job fo one run in the background at a
- specified time.
- Behaviour is similar to the UNIX AT command,but the code was
- completely by myself.
-
- There are 3 possibilities to specify the time :
-
- - at now + 12minutes
- at now + 3hours
- at now + 2 days
- at now + 1 week
-
- As you see you can omit the space between the timevalue and type.
-
- - at 12:30
-
- If the time is earlier than the current time the job will run
- next day at the specified time.
-
- - at 12:30 27-3
-
- If the time is earlier than the current time the job will run
- next year at the specified time.
-
- The command is read from stdin. Any CR or LF or Ctrl-D will finish
- the command and submit the job to the Crondaemon.
- In this way it is also possible to use a pipe and echo to specify
- the command (only from a shell of course !):
-
- echo '/bin/ls -la' | at now + 2days
-
- Remarks:
-
- - This program can only run if the CROND (also by me) is running in
- the background of your (MULTITOS) ATARI.
-
- - The files at.allow and at.deny are not implemented as I consider this
- useless on a simple ATARI.
-
- - The program needs a passwd file to check the username (which is read
- from USERENV variable, process uid or from cmdline option -u <user>).
-
- - The only valid timename is 'now'. So names like 'tomorrow', 'midnight'
- and others that can be used on some UNIX systems are not allowed.
-
- Any questions or suggestions about this program can be send to:
- lemmens@dv.twi.tudelft.nl
- */
-
- #include "cron.h"
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <pwd.h>
- #include <time.h>
- #include <errno.h>
-
- extern char *ux2dos(char *string);
- extern void PokeDaemon(char cmd);
-
- static enum { list, delete, newjob } Option=newjob;
- static char *Days[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
- static char *Months[] = {NULL,"Jan","Feb","Mar","Apr","May",
- "Jun","Jul","Aug","Sep","Okt","Nov","Dec"};
-
- static void usage(void)
- {
- fprintf(stderr,"usage: %s [-u user] [-l|-r <nr>|<time>]\n", PROGNAME);
- fprintf(stderr," -l : list all atjobs\n");
- fprintf(stderr," -r <nr> : remove jobnr <nr>\n");
- fprintf(stderr," <time> : read new job from stdin\n\n");
- fprintf(stderr," timespec : 'now + <nr> minutes|hours|days|weeks'");
- fprintf(stderr," or 'mm:hh [dd-mm]'\n");
- exit(1);
- }
-
- static int ParseArgs(int argc,char * argv[],char *User,int *JobId)
- { char *tmp,uflag=0;
- struct passwd *pwent;
- int skip=1; /* always skip argv[0] */
-
- while(--argc>0) /* parse options */
- { if(*argv[1]=='-')
- { switch(*(++argv[1]))
- {
- case 'u':
- if(argv[2] == NULL || ! isalpha(*argv[2]))
- usage();
- strcpy(User, argv[2]);
- uflag=1;
- argv++; argc--;
- skip+=2;
- break;
- case 'l':
- Option = list;
- skip++;
- break;
- case 'r':
- Option = delete;
- if(argv[2] == NULL || ! isdigit(*argv[2]))
- usage();
- *JobId = atoi(argv[2]);
- argv++; argc--;
- skip+=2;
- break;
- default: usage();
- break;
- }
- }
- argv++;
- }
-
- if(!uflag) /* determine username */
- { *User = '\0';
- if((tmp=getenv(USERENV)) != NULL)
- strcpy(User,tmp);
- else if((pwent = getpwuid(Pgetuid())) == NULL)
- strcpy(User,pwent->pw_name);
- }
- if(getpwnam(User) == NULL)
- { fprintf(stderr,PROGNAME " : User unknown.\n");
- exit(1);
- }
- return skip;
- }
-
- static void ListCmd(char *User)
- { char *dirname = ATDIR;
- char atname[MAX_FNAME];
- char *fileid;
- int x,min,hour,mday,mon,wday;
- FILE *atjob;
- long DirHandle;
- struct dirent d_ent;
-
- if((DirHandle=opendir(ux2dos(dirname))) < 0)
- { printf("No jobs for %s\n",User);
- exit(0);
- }
-
- /* Rem. : Dreaddir is MINT specific call */
-
- while(Dreaddir(sizeof(d_ent),DirHandle,&d_ent.d_ino) == 0L)
- {
- for(x=0;d_ent.d_name[x] != '\0';x++)
- d_ent.d_name[x] = tolower(d_ent.d_name[x]);
-
- if(strncmp(d_ent.d_name,User,strlen(User)))
- continue; /* job from other user */
-
- sprintf(atname,"%s/%s",dirname,d_ent.d_name);
-
- if((atjob = fopen(ux2dos(atname),"r")) == NULL)
- { fprintf(stderr,"Read failed for %s\n",atname);
- exit(1);
- }
-
- if((fileid = strchr(d_ent.d_name,'.')) != NULL)
- *fileid++ = '\0'; /* separate name and extension */
- else
- { fprintf(stderr,"Illegal filename %s\n",atname);
- continue;
- }
- if(fscanf(atjob,"%d%d%d%d%d",&min,&hour,&mday,&mon,&wday) < 5)
- { fprintf(stderr,"Invalid job in %s\n",atname);
- continue;
- }
- fclose(atjob);
-
- printf("User: % 10s Jobnr: %3.3s ",d_ent.d_name,fileid);
- printf("Starttime: %02d:%02d %s %s-%02d\n",hour,min,
- Days[wday],Months[mon],mday);
- }
- }
-
- static void DeleteCmd(char *User,int JobId)
- { extern errno;
- char atname[MAX_FNAME];
-
- sprintf(atname, "%s/%s.%03d",ATDIR,User,JobId);
- if (remove(ux2dos(atname)))
- { if (errno == ENOENT)
- fprintf(stderr, "Job %d for %s not found\n",JobId, User);
- else
- perror(atname);
- exit(1);
- }
- printf("Atjob %d for %s removed\n",JobId, User);
-
- PokeDaemon(EXTERNBUILD); /* send a reread signal to daemon */
- }
-
- static void TimeError(void)
- { fprintf(stderr,"Invalid time specification\n");
- exit(1);
- }
-
- static struct tm *ParseJobTime(char *timemask)
- { struct tm *attm;
- time_t curti,atti;
- long value;
- char *dtstr,*tmstr,timesymbol;
-
- time(&curti);
-
- if(! strncmp("now",timemask,3))
- { atti = curti;
- if((tmstr=strchr(timemask,'+')) == NULL)
- TimeError();
- if(sscanf(++tmstr,"%ld%1s",&value,×ymbol) < 2)
- TimeError();
- switch(toupper(timesymbol))
- { case 'M': atti += value * 60L;
- break;
- case 'H': atti += value * 3600L;
- break;
- case 'D': atti += value * 3600L * 24L;
- break;
- case 'W': atti += value * 3600L * 24L * 7L;
- break;
- default: TimeError();
- }
- attm = localtime(&atti);
- }
- else
- { attm = localtime(&curti);
- if(sscanf(timemask,"%d:%d",&attm->tm_hour,&attm->tm_min) < 2)
- TimeError();
-
- if((dtstr=strchr(timemask,' ')) != NULL)
- { if(sscanf(dtstr,"%d-%d",&attm->tm_mday,&attm->tm_mon) < 2)
- TimeError();
- attm->tm_mon--; /* months are from 0-11 */
- }
- if((atti = mktime(attm)) < curti)
- { if(dtstr == NULL)
- { atti += 3600L * 24L; /* next day */
- attm = localtime(&atti);
- }
- else
- attm->tm_year++; /* next year */
- atti = mktime(attm);
- attm = localtime(&atti);
- }
- }
- return attm;
- }
-
- static void NewJobCmd(char *User,int argc,char *argv[])
- { extern errno;
- char atname[MAX_FNAME];
- char atcmd[MAX_COMMAND];
- char timemask[MAX_TEMPSTR];
- int x,charcnt=0,jobcnt=0;
- FILE *atjob;
- struct tm *attm;
- char c;
-
- for(x=0;x<argc && strlen(timemask) < (MAX_TEMPSTR - 1);x++)
- { strcat(timemask,argv[x]); /* concatenate into one string */
- if(x<argc-1)
- strcat(timemask," "); /* not after last argv */
- }
-
- while(jobcnt < 1000) /* range from 000 to 999 */
- { sprintf(atname, "%s/%s.%03d", ATDIR, User, jobcnt);
- if(fopen(ux2dos(atname),"r") == NULL)
- break; /* unused entry found */
- jobcnt++;
- }
- if(jobcnt >= 1000)
- { fprintf(stderr,"Max. number of jobs reached (1000)\n");
- exit(1);
- }
-
- ParseJobTime(timemask);
- /* Check time to prevent typing your command for nothing ! */
-
- while(read(fileno(stdin),&c,1),c != '\4' && charcnt < MAX_COMMAND - 1)
- { /* CR or LF also end a command in this at implementation */
- if(c == '\n' || c == '\r')
- break;
- atcmd[charcnt++] = c;
- }
-
- attm = ParseJobTime(timemask);
- /* After reading command, to avoid starttime is already old ! */
-
- if((atjob=fopen(atname,"w")) == NULL)
- { fprintf(stderr,"Write failed for %s\n",atname);
- exit(1);
- }
-
- fprintf(atjob,"%02d %02d %02d %02d %02d %s\n",attm->tm_min,
- attm->tm_hour,attm->tm_mday,attm->tm_mon+1,attm->tm_wday,atcmd);
-
- fclose(atjob);
-
- attm->tm_sec=0;
- printf("\nJob %d wil be started at %s",jobcnt,asctime(attm));
-
- PokeDaemon(EXTERNBUILD); /* send reread signal to daemon */
- }
-
- void main(int argc,char *argv[])
- { static int JobId;
- static char User[MAX_UNAME];
- int skip;
-
- if(argc <= 1) usage();
-
- skip = ParseArgs(argc, argv, User, &JobId);
- argv += skip;
- argc -= skip;
-
- switch (Option)
- {
- case list : ListCmd(User); break;
- case delete : DeleteCmd(User,JobId); break;
- case newjob : NewJobCmd(User,argc,argv); break;
- default : usage(); break;
- }
- exit(0);
- }
-